package utils

import (
	"google.golang.org/protobuf/types/known/timestamppb"
	"google.golang.org/protobuf/types/known/wrapperspb"
	"time"
)

// ConvertTimestampToTime proto时间戳转换成时间
func ConvertTimestampToTime(ts *timestamppb.Timestamp) time.Time {
	return ts.AsTime()
}

// ConvertTimeToTimestamp 时间转换成proto时间戳
func ConvertTimeToTimestamp(t time.Time) *timestamppb.Timestamp {
	return timestamppb.New(t)
}

func WrapString(val *string) *wrapperspb.StringValue {
	return wrapperspb.String(*val)
}

func UnwrapString(w *wrapperspb.StringValue) *string {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapInt32(val *int32) *wrapperspb.Int32Value {
	return wrapperspb.Int32(*val)
}
func UnwrapInt32(w *wrapperspb.Int32Value) *int32 {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapInt64(val *int64) *wrapperspb.Int64Value {
	return wrapperspb.Int64(*val)
}
func UnwrapInt64(w *wrapperspb.Int64Value) *int64 {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapBool(val *bool) *wrapperspb.BoolValue {
	return wrapperspb.Bool(*val)
}
func UnwrapBool(w *wrapperspb.BoolValue) *bool {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapDouble(val *float64) *wrapperspb.DoubleValue {
	return wrapperspb.Double(*val)
}
func UnwrapDouble(w *wrapperspb.DoubleValue) *float64 {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapFloat(val *float32) *wrapperspb.FloatValue {
	return wrapperspb.Float(*val)
}
func UnwrapFloat(w *wrapperspb.FloatValue) *float32 {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapUint64(val *uint64) *wrapperspb.UInt64Value {
	return wrapperspb.UInt64(*val)
}
func UnwrapUint32(w *wrapperspb.UInt32Value) *uint32 {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapUint32(val *uint32) *wrapperspb.UInt32Value {
	return wrapperspb.UInt32(*val)
}

func UnwrapUint64(w *wrapperspb.UInt64Value) *uint64 {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapBytes(val *[]byte) *wrapperspb.BytesValue {
	return wrapperspb.Bytes(*val)
}
func UnwrapBytes(w *wrapperspb.BytesValue) *[]byte {
	if w == nil {
		return nil
	}
	v := w.Value
	return &v
}

func WrapTimestamp(val *time.Time) *timestamppb.Timestamp {
	return timestamppb.New(*val)
}
func UnwrapTimestamp(w *timestamppb.Timestamp) *time.Time {
	if w == nil {
		return nil
	}
	v := w.AsTime()
	return &v
}

type Int interface {
	*wrapperspb.Int64Value | *wrapperspb.Int32Value | *wrapperspb.UInt64Value | *wrapperspb.UInt32Value
}

func ToInt[T Int](val T) *int {
	if val == nil {
		return nil
	}
	var intVal int
	switch v := any(val).(type) {
	case *wrapperspb.Int64Value:
		intVal = int(v.Value)
	case *wrapperspb.Int32Value:
		intVal = int(v.Value)
	case *wrapperspb.UInt64Value:
		intVal = int(v.Value)
	case *wrapperspb.UInt32Value:
		intVal = int(v.Value)
	default:
		return nil
	}
	return &intVal
}

type Float interface {
	*wrapperspb.FloatValue | *wrapperspb.DoubleValue
}

func ToFloat64[T Float](val T) *float64 {
	if val == nil {
		return nil
	}
	var floatVal float64
	switch v := any(val).(type) {
	case *wrapperspb.FloatValue:
		floatVal = float64(v.Value)
	case *wrapperspb.DoubleValue:
		floatVal = v.Value
	default:
		return nil
	}
	return &floatVal
}
